package com.xinyue.design.template;

/**
 * 定义一个操作中的算法的骨架，而将一些步骤延迟到子类中。模板方法是：子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
 * 模板方法模式是通过把不变行为搬移到超类，去除子类中的重复代码来体现它的优势。模板方法模式提供一个很好的方法复用平台。帮助子类摆脱重复的不变行为的纠缠。
 * 
 * 模板方法模式使用：
 * 知道一个算法所需的关键步聚，并确定了这些步聚的执行顺序。但是某些步聚的具体实现是未知的.
 * <core>
 * 模板方法的使用条件：
 * 1、存在大量的共用方法。
 * 2、算法数量及步骤确定，而某些步骤具体实现未知。
 * 3、算法数量确定，但是步骤未知。
 * <core>
 */
//利润计算
public abstract class Profit {

	protected int costCount;//进货量
	protected double costPrice;//进货单价
	protected int saleCount;//销售量
	protected double salePrice;//销售单价
	protected double nowPrice;//物品当前进价
	
	/**商品销售中的其他支出费用
	 * <test>自定义算法，每种物品的销售支出费用是不一样的。
	 * protected只有子类可见，不公开
	 */
	protected abstract double outlay();
	
	/**货物成本计算
	 * <test>该算法确定且统一
	 * protected只有子类可见，不公开
	 */
	protected double cost() {
		return costCount * costPrice;
	};
	
	/**销售额计算
	 * <test>该算法确定且统一
	 * protected只有子类可见，不公开
	 */
	protected double sale() {
		return saleCount * salePrice;
	};
	
	/**剩余货物资产计算
	 * <test>该算法确定且统一
	 * protected只有子类可见，不公开
	 */
	protected double surplus() {
		
		return (costCount- saleCount) * nowPrice;
	};
	
	
	/**计算利润
	 * <test>该算法确定且统一
	 * 公开算法，外部可调用
	 */
	public double getProfit() {
		return sale() - cost() - outlay() + surplus();
	}
	
	/**计算总支出
	 * <test>该算法确定且统一
	 * 公开算法，外部可调用
	 */
	public double getCost() {
		return cost() + outlay();
	}
	
	/**计算利润率
	 * <test>该算法确定且统一
	 * 公开算法，外部可调用
	 */
	public String getPercentage() {
		return (getProfit() / (cost() + outlay()) * 100) + "%";
	}
}
